package solver;

import java.util.List;
import java.util.Scanner;

import model.EnhancedCostEvaluator;
import model.Problem;
import model.Process;
import model.Solution;

public class GrbExtraLeanIPModelBuidlerAnalyzer {
	Problem problem;
	Solution initial_solution;
	Solution current_solution;
	List<Integer> selectedProcesses;
	GrbExtraLeanIPModelBuilder grbExtraLeanIPModelBuilder;

	public GrbExtraLeanIPModelBuidlerAnalyzer(Problem problem,
			Solution initial_solution, Solution current_solution,
			List<Integer> selectedProcesses) {
		this.problem = problem;
		this.initial_solution = initial_solution;
		this.current_solution = current_solution;
		this.selectedProcesses = selectedProcesses;
		grbExtraLeanIPModelBuilder = new GrbExtraLeanIPModelBuilder(problem,
				selectedProcesses, true);
		grbExtraLeanIPModelBuilder.setInitialSolution(initial_solution);
		grbExtraLeanIPModelBuilder.setCurrentSolution(current_solution);
	}

	public void analyze() {
		System.out.println("Analyze problem ...");
		System.out
				.println("############### CURRENT SOLUTION BEFORE  ###############");
		EnhancedCostEvaluator ece = new EnhancedCostEvaluator();
		ece.setSolutionPair(initial_solution, current_solution);
		ece.computeCost();
		ece.printCostAnalysis();

		grbExtraLeanIPModelBuilder.includeAssignmentHardConstraints(true);
		grbExtraLeanIPModelBuilder.includeCapacityHardConstraints(true);
		grbExtraLeanIPModelBuilder.includeConflictHardConstraints(true);
		grbExtraLeanIPModelBuilder.includeSpreadHardConstraints(true);
		grbExtraLeanIPModelBuilder.includeDependencyHardConstraints(true);
		grbExtraLeanIPModelBuilder.includeTransientHardConstraints(true);

		grbExtraLeanIPModelBuilder.includeLoadCostSoftConstraints(true);
		grbExtraLeanIPModelBuilder.includeBalanceCostSoftConstraints(true);
		grbExtraLeanIPModelBuilder.includeProcessMoveCostSoftConstraints(true);
		grbExtraLeanIPModelBuilder.includeServiceMoveCostSoftConstraints(true);
		grbExtraLeanIPModelBuilder.includeMachineMovedCostSoftConstraints(true);
		grbExtraLeanIPModelBuilder.printActiveInactiveConstraints();
		System.out
				.println("########################################################");

		for (Integer p_id : selectedProcesses) {
			Process process = problem.getProcesses().get(p_id);
			System.out.printf("%s [INI_MACHINE=%d] [CUR_MACHINE=%d]\n",
					process.getEligibleMachinesInfo(),
					initial_solution.getMachineIdForProcessId(p_id),
					current_solution.getMachineIdForProcessId(p_id));
		}

		boolean saveLP=false;
		if (grbExtraLeanIPModelBuilder.solve(saveLP)) {
			System.out.println("solution found");
			Solution potential_solution = grbExtraLeanIPModelBuilder
					.saveToSolution();
			ece.setSolutionPair(initial_solution, potential_solution);
			ece.computeCost();
			ece.printNewSolutionCostAnalysis("POT Solution");
			if (ece.isFeasible()) {
				System.out.println("Feasible :)");
			} else {
				StringBuilder sb = new StringBuilder();
				sb.append("INITIAL_SOLUTION SELECTED PROCESSES");
				for (Integer p : selectedProcesses)
					sb.append(String.format("p%d->m%d\t", p,
							initial_solution.getMachineIdForProcessId(p)));
				sb.append("\n");
				sb.append("CURRENT_SOLUTION SELECTED PROCESSES");
				for (Integer p : selectedProcesses)
					sb.append(String.format("p%d->m%d\t", p,
							current_solution.getMachineIdForProcessId(p)));
				sb.append("\n");
				sb.append("POTENTIAL_SOLUTION SELECTED PROCESSES");
				for (Integer p : selectedProcesses)
					sb.append(String.format("p%d->m%d\t", p,
							potential_solution.getMachineIdForProcessId(p)));

				sb.append("\n");
				sb.append("INITIAL_SOLUTION ALL\n");
				for (int p = 0; p < problem.P; p++) {
					sb.append(String.format("p%d->m%d\t", p,
							initial_solution.getMachineIdForProcessId(p)));
					if ((p+1) % 8 == 0)
						sb.append("\n");
				}
				sb.append("\n");

				sb.append("CURRENT_SOLUTION ALL\n");
				for (int p = 0; p < problem.P; p++) {
					sb.append(String.format("p%d->m%d\t", p,
							current_solution.getMachineIdForProcessId(p)));
					if ((p+1) % 8 == 0)
						sb.append("\n");
				}
				sb.append("\n");

				sb.append("POTENTIAL_SOLUTION ALL\n");
				for (int p = 0; p < problem.P; p++) {
					sb.append(String.format("p%d->m%d\t", p,
							potential_solution.getMachineIdForProcessId(p)));
					if ((p+1) % 8 == 0)
						sb.append("\n");
				}
				sb.append("\n");
				System.out.println(sb.toString());

			}
		} else {
			System.out.println("no solution found");
		}
	}
}
